let uploader = {
    CHUNK_SIZE: 1 * 1024 * 1024,
    status: 'ready',
    per: 0,
    file: null,
    chunkIndex: 0,
    onStateChage: console.log,
    async start(file, onStateChage) {
        if (onStateChage && typeof onStateChage == 'function') {
            this.onStateChage = onStateChage;
        }
        this.chunkIndex = 0;
        this.per = 0;
        this.file = file;
        this.stateChange('uploading');
        this.up();
    },
    pause() {
        this.stateChange('pause');
    },
    resume() {
        this.stateChange('uploading');
        this.up();
    },
    cancel() {
        this.chunkIndex = 0;
        this.per = 0;
        this.file = null;
        this.stateChange('cancel');
    },
    stateChange(newStatus) {
        this.status = newStatus;
        this.onStateChage(newStatus, this.per);
    },
    async up() {
        if (!this.file || !this.file.size) {
            return;
        }
        let chunkCount = Math.ceil(this.file.size / this.CHUNK_SIZE);
        for (let i = this.chunkIndex; i < chunkCount; i++) {
            if (this.status == 'pause' || this.status == "cancel") {
                return;
            }
            let start = i * this.CHUNK_SIZE;
            let end = start + this.CHUNK_SIZE;
            await this.postFile(file, start, end, i, chunkCount);
            this.chunkIndex = i;
            this.per = parseInt((i * 100) / chunkCount);
            this.stateChange(this.status);
        }
        this.per = 100;
        this.stateChange('ready');
    },
    postFile(file, start, end, index, chunkCount) {
        return new Promise((resolve, reject) => {
            const blobFile = file.slice(start, end);
            const fd = new FormData();
            fd.append('file', blobFile);
            fd.append('fileName', file.name);
            fd.append('chunkIndex', index);
            fd.append('chunkCount', chunkCount);
            $.ajax({
                method: 'POST',
                url: '/upload',
                async: false,
                data: fd,
                contentType: false,
                processData: false,
                success: function (res) {
                    console.log(res);
                    setTimeout(function () {
                        resolve();
                    }, 10);
                }
            });
        });
    },

}
